package edu.isistan.matching.utils.serviceMatching;


import org.apache.log4j.Logger;

import edu.isistan.matching.structures.elements.OperationElement;
import edu.isistan.matching.structures.elements.TypeElement;
import edu.isistan.metamodel.DataType;
import edu.isistan.metamodel.Operation;

/**
 * Match hibrido que pondera un porcentaje de match estructural y match semantico
 * @author Mariano
 *
 */
public class HybridMatching extends AbstractMatching {
	
	static Logger logger = Logger.getLogger(HybridMatching.class);
	
	StructureMatching strucuteMatchAlg = new StructureMatching();
	
	SemanticMatching semanticMatchAlg = new SemanticMatching();

	/**
	 * Porcentaje del match estrucutural a considerar
	 */
	double alpha = 0.5d;
	double beta = 0.5d;

	public static int DOUBLE_PRECISION = 2;
	
	public HybridMatching() {
		super();
	}
	
	public HybridMatching(double alpha, double beta) {
		super();
		this.alpha = alpha;
		this.beta = beta;
	}

	public StructureMatching getStrucuteMatchAlg() {
		return strucuteMatchAlg;
	}

	public void setStrucuteMatchAlg(StructureMatching strucuteMatchAlg) {
		this.strucuteMatchAlg = strucuteMatchAlg;
	}

	public SemanticMatching getSemanticMatchAlg() {
		return semanticMatchAlg;
	}

	public void setSemanticMatchAlg(SemanticMatching semanticMatchAlg) {
		this.semanticMatchAlg = semanticMatchAlg;
	}

	@Override
	public double analyzeOperationMatching(Operation op1, Operation op2) {
		double strValue = redondear(alpha*getStrucuteMatchAlg().analyzeOperationMatching(op1, op2));
		double semValue = redondear(beta*getSemanticMatchAlg().analyzeOperationMatching(op1, op2));
		//TODO: se deben normalizar los valores para no obtener resultados desparejos
		logger.info("operation Matching: Struct "+strValue+"<->"+semValue+" Semantic");
		return strValue + semValue;
	}

	@Override
	public double analyzePrimitivesMatching(DataType tipo1, DataType tipo2) {
		double strValue = redondear(alpha*getStrucuteMatchAlg().analyzePrimitivesMatching(tipo1, tipo2));
		double semValue = redondear(beta*getSemanticMatchAlg().analyzePrimitivesMatching(tipo1, tipo2));
		//TODO: se deben normalizar los valores para no obtener resultados desparejos
		logger.info("Primitive Matching: Struct "+strValue+"<->"+semValue+" Semantic");
		return strValue + semValue;
	}
	
	/**
	 * Retorna el numero Double pasado por parametro redondeado según indique
	 * DOUBLE_PRECISION
	 * 
	 * @param numero
	 * @return
	 */
	public Double redondear(Double numero) {
		return (Math.round(numero * Math.pow(10, DOUBLE_PRECISION)) / Math.pow(10, DOUBLE_PRECISION));
	}
}
